using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.Base.Exceptions;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using Habanero.Faces.Base;
using Habanero.Faces.Win;

namespace FireStarterModeller.UI
{
    public class SuperClassControl : UserControlWin
    {
        private readonly IControlFactory _controlFactory;

        private DMClass _dmSubClass;
        private LookupComboBoxMapper _idLookupComboBoxMapper;
        private IButton discriminatorButton;

        public IPanelInfo InheritanceRelationshipPanelInfo { get; private set; }
        public ICheckBox HasSuperClassCheckBox { get; private set; }
        public ILabel DiscriminatorLabel { get; private set; }
        public ILabel IDLabel { get; private set; }
        public SuperClassLookupComboBoxMapper SuperClassLookupComboBoxMapper { get; private set; }
        public CollectionComboBoxMapper DiscriminatorLookupComboBoxMapper { get; private set; }

        public SuperClassControl(IControlFactory controlFactory)
        {
            _controlFactory = controlFactory;
            SetupHasSuperClassCheckBox();

            SetupInheritanceRelationshipPanel();
            RegisterForInheritanceTypeChanged();
            RegisterForSuperClassChanged();
            SetControlVisibility();

            this.Width = InheritanceRelationshipPanelInfo.UIForm.Width;

            BorderLayoutManager layoutManager = _controlFactory.CreateBorderLayoutManager(this);
            layoutManager.AddControl(InheritanceRelationshipPanelInfo.Panel, BorderLayoutManager.Position.Centre);
            layoutManager.AddControl(HasSuperClassCheckBox, BorderLayoutManager.Position.North);
            discriminatorButton = controlFactory.CreateButton("Create Descriminator", HandleCreateDiscriminatorClick);
            
            layoutManager.AddControl(discriminatorButton,BorderLayoutManager.Position.South);
            discriminatorButton.Enabled = false;
            UpdateState();
        }

        private void HandleCreateDiscriminatorClick(object sender, EventArgs eventArgs)
        {
            try
            {
               this.InheritanceRelationship.CreateDiscriminator();
            }
            catch (Exception ex)
            {
                GlobalRegistry.UIExceptionNotifier.Notify(ex, "", "Error ");
            }
        }

        private void SetupHasSuperClassCheckBox()
        {
            HasSuperClassCheckBox = _controlFactory.CreateCheckBox(false);
            HasSuperClassCheckBox.Text = "Has a super-class";
            ToolTip toolTip = new ToolTip();
            toolTip.SetToolTip((Control)HasSuperClassCheckBox, "Is this class inherited from another SubClass");
            HasSuperClassCheckBox.CheckedChanged += SuperClassCheckBox_OnCheckedChanged;
        }

        private void SetupInheritanceRelationshipPanel()
        {
            PanelBuilder panelBuilder = new PanelBuilder(_controlFactory);
            InheritanceRelationshipPanelInfo = panelBuilder.BuildPanelForForm(ClassDef.Get<DMInheritanceRelationship>().UIDefCol["default"].UIForm);
            PanelInfo.FieldInfoCollection mappers = InheritanceRelationshipPanelInfo.FieldInfos;
            SuperClassLookupComboBoxMapper = (SuperClassLookupComboBoxMapper) mappers["SuperClassID"].ControlMapper;
            DiscriminatorLookupComboBoxMapper = (CollectionComboBoxMapper) mappers["Discriminator"].ControlMapper;
            DiscriminatorLabel = (ILabel) mappers["Discriminator"].LabelControl;
            DiscriminatorLookupComboBoxMapper.OwningBoPropertyName = "PropertyName";
            _idLookupComboBoxMapper = (LookupComboBoxMapper)mappers["IdentityPropertyID"].ControlMapper;
            IDLabel = (ILabel)mappers["IdentityPropertyID"].LabelControl;
        }

        private void RegisterForInheritanceTypeChanged()
        {
            PanelInfo.FieldInfoCollection mappers = InheritanceRelationshipPanelInfo.FieldInfos;
            InheritanceTypeMapper = (LookupComboBoxMapper)mappers["InheritanceType"].ControlMapper;
            IComboBox inheritanceTypeComboBox = (IComboBox)InheritanceTypeMapper.Control;
            inheritanceTypeComboBox.SelectedIndexChanged += delegate { SetControlVisibility(); };
        }

        private void RegisterForSuperClassChanged()
        {
            this.SuperClassComboBox.SelectedIndexChanged += SuperClassComboBox_OnSelectedIndexChanged;
        }

        public DMClass SubClass
        {
            get { return _dmSubClass; }
            set
            {
                _dmSubClass = value;
                UpdateInheritanceRelationshipPanel();
                UpdateState();
            }
        }

        public LookupComboBoxMapper InheritanceTypeMapper { get; private set; }

        public IComboBox InheritanceTypeComboBox
        {
            get { return (IComboBox) InheritanceTypeMapper.Control; }
        }

        public IComboBox SuperClassComboBox
        {
            get { return (IComboBox) SuperClassLookupComboBoxMapper.Control; }
        }

        public IComboBox DiscriminatorComboBox
        {
            get { return (IComboBox) DiscriminatorLookupComboBoxMapper.Control; }
        }

        public IComboBox IDComboBox
        {
            get { return (IComboBox) _idLookupComboBoxMapper.Control; }
        }

        public DMInheritanceRelationship InheritanceRelationship
        {
            get { return InheritanceRelationshipPanelInfo.BusinessObject as DMInheritanceRelationship; }
            //get { return _dmSubClass != null ? _dmSubClass.InheritanceSuperClassRelationship : null; }
        }

        private void SuperClassCheckBox_OnCheckedChanged(object sender, EventArgs e)
        {
            try
            {
                if (HasSuperClassCheckBox.Checked)
                {
                    if (this.SubClass == null) throw new HabaneroArgumentException("SubClass", "SubClass cannot be null.");
                    CreateInheritanceRelationship();
                    discriminatorButton.Enabled = true;
                }
                else
                {
                    DeleteInheritanceRelationship();
                    discriminatorButton.Enabled = false;
                }
                UpdateInheritanceRelationshipPanel();
            }
            catch (Exception ex)
            {
                GlobalRegistry.UIExceptionNotifier.Notify(ex, "", "Error ");
            }
        }

        private void SuperClassComboBox_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                PopulateDiscriminatorCombo();
                UpdateIDPropList();
            }
            catch (Exception ex)
            {
                GlobalRegistry.UIExceptionNotifier.Notify(ex, "", "Error ");
            }
        }

        private void CreateInheritanceRelationship()
        {
            if (_dmSubClass == null) return;
            DMInheritanceRelationship inheritanceRelationship = _dmSubClass.InheritanceSuperClassRelationship;
            if (inheritanceRelationship != null && inheritanceRelationship.Status.IsNew
                && inheritanceRelationship.Status.IsDeleted)
            {
                inheritanceRelationship = null;
            }
            if (inheritanceRelationship == null)
            {
                _dmSubClass.InheritanceSuperClassRelationship = new DMInheritanceRelationship();
            }
        }

        private void DeleteInheritanceRelationship()
        {
            DMInheritanceRelationship inheritanceRelationship = InheritanceRelationship;
            if (inheritanceRelationship == null) return;
            inheritanceRelationship.SubClass = null;
            inheritanceRelationship.MarkForDelete();
            inheritanceRelationship.Save();
        }

        private void UpdateInheritanceRelationshipPanel()
        {
            DMInheritanceRelationship inheritanceRelationship = SubClass != null ? SubClass.InheritanceSuperClassRelationship : null;
            if (InheritanceRelationshipPanelInfo.BusinessObject != inheritanceRelationship)
            {
                InheritanceRelationshipPanelInfo.BusinessObject = null;
                UpdateDiscriminatorProps(inheritanceRelationship);
                InheritanceRelationshipPanelInfo.BusinessObject = inheritanceRelationship;
            }
            SuperClassLookupComboBoxMapper.SubClass = SubClass;
            UpdateIDPropList();
            UpdateState();
        }

        private void UpdateDiscriminatorProps(DMInheritanceRelationship inheritanceRelationship)
        {
            BusinessObjectCollection<DMProperty> discriminatorProps = null;
            if (inheritanceRelationship != null && inheritanceRelationship.SuperClass != null)
            {
                discriminatorProps = inheritanceRelationship.SuperClass.Properties;
            }
            DiscriminatorLookupComboBoxMapper.BusinessObjectCollection = discriminatorProps ?? new BusinessObjectCollection<DMProperty>();
        }

        private void UpdateIDPropList()
        {
            _idLookupComboBoxMapper.LookupList = GetIDLookupList();
        }

        private Dictionary<string, string> GetIDLookupList()
        {
            if (this.InheritanceRelationship == null) return new Dictionary<string, string>();
            return this.InheritanceRelationship.GetIDLookupList();
        }

        private void PopulateDiscriminatorCombo()
        {
            string boID = (string) this.SuperClassComboBox.SelectedValue;
            if (boID == null) return;
            DMClass superClass = BORegistry.DataAccessor.BusinessObjectLoader.GetBusinessObjectByValue<DMClass>(boID);
            if (superClass == null) return;
            if (!IsDiscriminatorNullOrEmpty(superClass))
            {
                string discriminator = superClass.InheritanceSuperClassRelationship.Discriminator;
                DMProperty discriminatorProp = (DMProperty) superClass.InheritanceSuperClassRelationship.SuperClass.GetDMProperty(discriminator);
                DiscriminatorLookupComboBoxMapper.BusinessObjectCollection = 
                    new BusinessObjectCollection<DMProperty> {discriminatorProp};
                this.InheritanceRelationship.Discriminator = discriminator;
            }
            else
            {
                DiscriminatorLookupComboBoxMapper.BusinessObjectCollection = superClass.Properties;
            }
        }

        private static bool IsDiscriminatorNullOrEmpty(DMClass superClass)
        {
            return superClass.InheritanceSuperClassRelationship == null ||
                   String.IsNullOrEmpty(superClass.InheritanceSuperClassRelationship.Discriminator);
        }

        private void UpdateState()
        {
            bool hasSubClass = SubClass != null;
            DMInheritanceRelationship inheritanceRelationship = hasSubClass ? SubClass.InheritanceSuperClassRelationship : null;
            bool hasInheritanceRelationship = inheritanceRelationship != null;

            this.Enabled = hasSubClass;
            HasSuperClassCheckBox.Checked = hasInheritanceRelationship;
            InheritanceRelationshipPanelInfo.Panel.Enabled = hasInheritanceRelationship;
        }

        private void SetControlVisibility()
        {
            string selectedInheritanceType = Convert.ToString(InheritanceTypeComboBox.SelectedValue);
            bool showDiscriminatorCombo = selectedInheritanceType == ORMapping.ClassTableInheritance.ToString() ||
                                          selectedInheritanceType == ORMapping.SingleTableInheritance.ToString();
            bool showIDCombo = selectedInheritanceType == ORMapping.ClassTableInheritance.ToString();
            DiscriminatorComboBox.Visible = showDiscriminatorCombo;
            IDComboBox.Visible = showIDCombo;
            DiscriminatorLabel.Visible = showDiscriminatorCombo;
            IDLabel.Visible = showIDCombo;
        }

       
    }
}